#pragma once

#include "constants.h"

#undef max
#undef min

namespace roy {

    namespace math {

        // min
        template <typename T>
            inline T min(const T& a, const T& b)
        {
            return a < b ? a : b;
        }

        // max
        template <typename T>
            inline T max(const T& a, const T& b)
        {
            return a > b ? a : b;
        }

        // abs
        template <typename T>
            inline T abs(const T& a)
        {
            return (a >= zero<T>()) ? a : -a;
        }

        // is_eq
        template <typename T>
            inline bool is_eq(const T& a, const T& b)
        {
            return abs(a - b) <= eps<T>();
        }

        // is_gt
        template <typename T>
            inline bool is_gt(const T& a, const T& b)
        {
            return a > b + eps<T>();
        }

        // is_lt
        template <typename T>
            inline bool is_lt(const T& a, const T& b)
        {
            return a < b - eps<T>();
        }

        // is zero
        template <typename T>
            inline bool is_zero(const T& a)
        {
            return is_eq(a, zero<T>());
        }

        // is_positive
        template <typename T>
            inline bool is_positive(const T& a)
        {
            return is_gt(a, zero<T>());
        }

        // is_negative
        template <typename T>
            inline bool is_negative(const T& a)
        {
            return is_lt(a, zero<T>());
        }

        // sq
        template<typename T>
            inline T sq(const T& a)
        {
            return a * a;
        }

        // clamp
        template <typename T>
            inline T clamp(const T& x, const T& a, const T& b)
        {
            return x < a ? a : (x > b ? b : x);
        }

        // clamp_into
        template <typename T>
            inline void clamp_into(T& x, const T& a, const T& b)
        {
            x = x < a ? a : (x > b ? b : x);
        }

        // degree_to_radian
        template <typename R>
            inline R degree_to_radian(const R& degree)
        {
            return degree * pi<R>() / 180;
        }

        template <typename R>
            inline R radian_to_degree(const R& radian)
        {
            return radian * 180 / pi<R>();
        }

    }

}

